home *** CD-ROM | disk | FTP | other *** search
/ Mac-Source 1994 July / Mac-Source_July_1994.iso / C and C++ / Libraries / File class library / sources / CIsleFile.c < prev    next >
Text File  |  1992-10-08  |  8KB  |  328 lines

  1. /*
  2.  
  3.   CIsleFile.c
  4.   Superclass:    CFile
  5.  
  6.      CFile plus directory manipulation.
  7.  
  8.   October 8, 1992  isl
  9.   
  10. */
  11.  
  12. #include    <CIsleFile.h>
  13.  
  14. extern    OSType    gSignature;                    //    Owner stamp
  15.  
  16. /*=====================*/
  17. /*===---------------===*/
  18.  
  19. void CIsleFile::IIsleFile(void)
  20. Begin
  21.     IFile();
  22.     
  23.     fSuper= False;                                        //    We will assume the worse
  24.     
  25.     if (gSystem.hasGestalt)
  26.     {
  27.         long    response;                                    //    The response from the Gestalt enquiry
  28.         
  29.         if (Gestalt(gestaltFindFolderAttr, &response) == noErr)
  30.             if ((response & (1 << gestaltFindFolderPresent)))
  31.                 fSuper= True;                                //    We may rely on System 7 Finder goodies
  32.     }
  33. End
  34.  
  35. /*===---------------===*/
  36.  
  37. void    CIsleFile::CreateNew(OSType creator, OSType type)
  38. Begin
  39.     if (ExistsOnDisk())
  40.         MoveToTrash();                                    //    Get rid of this copy
  41.     
  42.     FailOSErr( HCreate(volNum, dirID, name, creator, type) );
  43. End
  44.                                 
  45. /*===---------------===*/
  46.  
  47. void CIsleFile::ResolveFileAlias(void)
  48. Begin
  49.     FSSpec     fileSpec;
  50.     Boolean    isFolder;
  51.     Boolean    wasAliased;
  52.     
  53.     if (!gSystem.hasAliasMgr) return;
  54.     
  55.     CopyPString(name, fileSpec.name);
  56.     fileSpec.parID=     dirID;
  57.     fileSpec.vRefNum= volNum;
  58.     
  59.     FailOSErr( ResolveAliasFile(&fileSpec, True, &isFolder, &wasAliased) );
  60.     
  61.     if (wasAliased)                                //    Copy back specification
  62.     {
  63.         CopyPString( fileSpec.name, name);
  64.         dirID=     fileSpec.parID;
  65.         volNum= fileSpec.vRefNum;
  66.     }
  67. End
  68.                                 
  69. /*===---------------===*/
  70.  
  71. void CIsleFile::GetPath(Str255 path, Str255 delimiter)
  72. Begin
  73.     path[0]= 0;                                        //    Initialize the path
  74.  
  75.     CollectPath(path, delimiter, (FSSpec*)Null);
  76. End
  77.  
  78. /*===---------------===*/
  79.  
  80. void CIsleFile::CollectPath(Str255 path, Str255 delimiter, FSSpec* leafSpec)
  81. Begin
  82.     FSSpec    fileSpec;                            //    The file/folder specification
  83.     long        directory;                        //    The target's directory
  84.     OSErr        error;                                //    Possible error condition
  85.     Str255    leafName= "\p";                //    The name of a leaf in the directory tree
  86.     
  87.     if (!leafSpec)
  88.     {
  89.         GetFSSpec(&fileSpec);                //    Specifications of the actual file
  90.         CollectPath(path, delimiter, &fileSpec);
  91.     }
  92.     else
  93.     {
  94.         if (leafSpec->parID == fsRtParID)
  95.         {
  96.             return;                                        //    We are the root -- the end of recursion
  97.         }
  98.         else
  99.         {                                                        //    We have a parent directory
  100.             directory= leafSpec->parID;
  101.             error= MakeFSSpec(volNum, directory, leafName, kDirectory, &fileSpec);
  102.                                                                 //    I should really be checking for errors,
  103.                                                                 //    but the only possible error is file not found
  104.                                                                 //    and it is not bloody likely
  105.             CollectPath(path, delimiter, &fileSpec);
  106.             ConcatPStrings(fileSpec.name, delimiter);
  107.         }
  108.     }
  109.     
  110.     ConcatPStrings(path, fileSpec.name);
  111. End
  112.  
  113. /*===---------------===*/
  114.  
  115. Boolean CIsleFile::IsStationery(void)
  116. Begin
  117.     Boolean    fStationery= False;        //    Assume not
  118.  
  119.     if (fSuper)
  120.     {                                                            //    We are using System 7 or later
  121.         FInfo    fileInfo;                            //    Information about our file
  122.         
  123.         GetMacFileInfo(&fileInfo);
  124.         
  125.         if (fileInfo.fdFlags & kStationery)
  126.             fStationery= True;
  127.     }
  128.     
  129.     return    fStationery;
  130. End
  131.  
  132. /*===---------------===*/
  133.  
  134. void CIsleFile::GetMacCatInfo(CInfoPBPtr specs)
  135. Begin
  136.     specs->dirInfo.ioCompletion=    Null;
  137.     specs->dirInfo.ioNamePtr=            name;
  138.     specs->dirInfo.ioVRefNum=            volNum;
  139.     specs->dirInfo.ioFDirIndex=        kDefault;
  140.     specs->dirInfo.ioDrDirID=            dirID;
  141.         
  142.     FailOSErr( PBGetCatInfo(specs, False) );
  143. End
  144.  
  145.  
  146. /*===---------------===*/
  147.  
  148. void CIsleFile::SetMacCatInfo(CInfoPBPtr specs)
  149. Begin
  150.     specs->dirInfo.ioCompletion=    Null;
  151.     specs->dirInfo.ioNamePtr=            name;
  152.     specs->dirInfo.ioVRefNum=            volNum;
  153.     specs->dirInfo.ioFDirIndex=        kDefault;
  154.     specs->dirInfo.ioDrDirID=            dirID;
  155.         
  156.     FailOSErr( PBSetCatInfo(specs, False) );
  157. End
  158.  
  159.  
  160. /*===---------------===*/
  161.  
  162. void CIsleFile::SetMacFileInfo(FInfo* fileInfo)
  163. Begin
  164.     FailOSErr( HSetFInfo(volNum, dirID, name, fileInfo) );
  165. End
  166.  
  167. /*===---------------===*/
  168.  
  169. Boolean CIsleFile::GoodType(OSType fileType)
  170. Begin
  171.     FInfo    fileInfo;
  172.     
  173.     GetMacFileInfo(&fileInfo);
  174.     
  175.     return (fileType == fileInfo.fdType);
  176. End
  177.  
  178. /*===---------------===*/
  179.  
  180. void CIsleFile::MakeStationery(Boolean fStationery)
  181. Begin
  182.     if (fSuper)
  183.     {                                                            //    We are using System 7 or later
  184.         FInfo    fileInfo;                            //    Information about our file
  185.         
  186.         GetMacFileInfo(&fileInfo);
  187.                                                                 //    Toggle the stationery flag to ON
  188.         if (fStationery)
  189.             fileInfo.fdFlags|= kStationery;
  190.         else
  191.             fileInfo.fdFlags&= (~kStationery);
  192.         
  193.         SetMacFileInfo(&fileInfo);
  194.     }
  195. End
  196.  
  197.  
  198. /*===---------------===*/
  199.  
  200. void CIsleFile::FindCreatorType(short vRefNum, long directory, OSType creator, OSType type, Boolean inside)
  201. Begin
  202.     CInfoPBRec            specs;                        //    Specifics of the file or folder
  203.     OSErr                        error;                        //    A possible error condition
  204.     register short    index;                        //    Entry index
  205.     
  206.     specs.hFileInfo.ioCompletion=    Null;
  207.     specs.hFileInfo.ioNamePtr=        name;
  208.     specs.hFileInfo.ioVRefNum=        vRefNum;
  209.     
  210.     for(index= 1; !fGood; index++)
  211.     {
  212.         specs.hFileInfo.ioDirID=            directory;
  213.         specs.hFileInfo.ioFDirIndex=    index;
  214.     
  215.         error= PBGetCatInfo(&specs, False);
  216.         if (error)
  217.             return;                                                //    No more entries!
  218.         
  219.         if ((specs.hFileInfo.ioFlFndrInfo.fdType == type
  220.             &&    specs.hFileInfo.ioFlFndrInfo.fdCreator == creator))
  221.         {
  222.             volNum= vRefNum;                            //    Set volume number
  223.             dirID=    directory;                        //    Set the directory
  224.                                                                         //    The name is set for us!
  225.             fGood= True;                                    //    Found what we were looking for.
  226.             return;
  227.         }
  228.         
  229.         if (inside && (specs.hFileInfo.ioFlAttrib & kDirTest))
  230.             FindCreatorType(vRefNum, specs.dirInfo.ioDrDirID, creator, type, True);
  231.     }
  232. End
  233.  
  234. /*===---------------===*/
  235.  
  236. OSErr CIsleFile::MakeFSSpec(short vRefNum, long directory, StringPtr leafName, short index, FSSpec* fileSpec)
  237. Begin
  238.     OSErr    error;                                //    A possible error condition
  239.  
  240.     if (fSuper)
  241.     {                                                        //    We can use System 7 calls!
  242.         error= FSMakeFSSpec(vRefNum, directory, leafName, fileSpec);
  243.     }
  244.     else
  245.     {                                                        //    Bleagh, System 6
  246.         CInfoPBRec    specs;                //    Current leaf specifications
  247.         
  248.         specs.dirInfo.ioCompletion= Null;
  249.         specs.dirInfo.ioNamePtr=        leafName;
  250.         specs.dirInfo.ioVRefNum=        vRefNum;
  251.         specs.dirInfo.ioFDirIndex=    index;
  252.         specs.dirInfo.ioDrDirID=        directory;
  253.         
  254.         if (error= PBGetCatInfo(&specs, False) )
  255.             ErrorAlert(error, 0);        //    Display a generic error alert
  256.         else
  257.         {
  258.             fileSpec->vRefNum=    vRefNum;                                                    //    The volume reference number
  259.             fileSpec->parID=        specs.dirInfo.ioDrParID;                    //    Current leaf's parent directory
  260.             CopyPString(specs.dirInfo.ioNamePtr, fileSpec->name);    //    Current leaf's name (file or folder)
  261.             
  262.             error= noErr;
  263.         }
  264.     }
  265.     
  266.     return error;
  267. End
  268.  
  269.  
  270. /*===---------------===*/
  271.  
  272. void CIsleFile::MoveToTrash(void)
  273. Begin
  274.     if (fSuper)
  275.     {                                                        //    Relocate into the Trash
  276.         short        trashVolume;            //    Volume containing our Trash folder (should be same)
  277.         long        trashDirID;                //    ID of the local Trash directory
  278.         FSSpec    trashSpec;                //    Specifications of the trash file
  279.         FSSpec    goodSpec;                    //    Specifications of the good file
  280.         FInfo        fileInfo;                    //    File information record
  281.         
  282.         FailOSErr( FindFolder(volNum, kTrashFolderType, kDontCreateFolder, &trashVolume, &trashDirID) );
  283.         GetFSSpec(&goodSpec);            //    Specifications of the current file (to be removed)
  284.         GetMacFileInfo (&fileInfo);
  285.         
  286.         SpecifyHFS(name, trashVolume, trashDirID);
  287.         CreateUniqueNew(fileInfo.fdCreator, fileInfo.fdType);
  288.         GetFSSpec(&trashSpec);        //    Create the impostor in ther Trash Folder
  289.         
  290.         FailOSErr( FSpExchangeFiles (&trashSpec, &goodSpec) );
  291.         
  292.         SpecifyFSSpec(&goodSpec);    //    We are working with the original again
  293.     }
  294.             
  295.     ThrowOut();                                    //    Simply delete the file
  296. End
  297.  
  298. /*===---------------===*/
  299.  
  300.  
  301. void CIsleFile::CreateUniqueNew(OSType creator, OSType type)
  302. Begin
  303.     OSErr    error;                                    //    Possible error condition
  304.     Str63    bogusName;                            //    We need to create a new name to avoid a conflict
  305.     char*    lastLetter;                            //    The last letter in the name
  306.     char    unique;                                    //    A character that will make the name unique
  307.  
  308.     unique= '0';
  309.     if (*name < 63)
  310.         (*name)++;                                    //    We will add a character
  311.     lastLetter= (char*)(name + *name);
  312.     
  313.     do                                                        //    We need to rename it
  314.     {
  315.         *lastLetter= unique++;            //    Insert the unique character and increment it in case we will need it
  316.         if ((unique > 'Z') && ExistsOnDisk())
  317.         {
  318.             ThrowOut();                                //    This has gone far enough.  Just delete the sucker!
  319.             break;
  320.         }
  321.     }
  322.     while (ExistsOnDisk());
  323.     
  324.     CreateNew(creator, type);
  325. End
  326.  
  327. /*===---------------===*/
  328. /*=====================*/